<script setup lang="ts">
import {onBeforeUnmount, onMounted, ref, shallowRef, watch} from 'vue'
import {useRoute} from 'vue-router'
import {isEmptyString} from "@/utils/string";
import {formatDate} from "@/utils/time";
import ClickToggleCounter from "@/components/feedback/ClickToggleCounter.vue";
import {Editor} from "@wangeditor/editor-for-vue";
import UserPostInfo from "@/components/common/UserPostInfo.vue";
import {
  ArticleCommentPageReq,
  ArticleCommentPageResp, ArticleCommentPublishReq,
  ArticleDetailResp,
  ArticleRecentReq,
  ArticleRecentResp,
  ArticleStarReq,
  ArticleCommentReplyPublishReq, ArticleCommentRepliesResp
} from "@/api/article/types";
import {
  getArticleDetail,
  pageArticleComment,
  publishArticleComment, publishArticleCommentReply,
  queryRecentArticle,
  starArticle
} from "@/api/article";
import {ElMessage} from "element-plus";
import {formatNumberSimple} from "@/utils/math";
import * as UserApi from "@/api/user"
import * as FileApis from "@/api/file";
import * as UserTypes from "@/api/user/types";
import RecentArticleList from "@/components/article/RecentArticleList.vue";
import {ChatDotSquare, Close} from "@element-plus/icons-vue";
import {useLoginStore} from "@/store/login"
import UserAvatar from "@/components/common/UserAvatar.vue";
import {IDomEditor} from "@wangeditor/editor";
import SysMessageDialog from "@/components/feedback/SysMessageDialog.vue";


const loginStore = useLoginStore()
const route = useRoute()
const dataLoaded = ref(false)
const article = ref<ArticleDetailResp>()
const recentArticle = ref<ArticleRecentResp[]>([])
const contentEditorRef = shallowRef()
let contentHeaders = [];
const showCatalog = ref(true)//是否显示目录
const authorInfo = ref<UserTypes.UserDetailResp>()
const showSysMessageChatDialog = ref(false)
//关注
const following = ref(false)
//评论列表
const articleComments = ref<ArticleCommentPageResp[]>([])
const articleCommentPage = ref(1)
const articleCommentHasMore = ref(false)
const loadingMoreArticleComment = ref(false)
//评论提交
const commentInput = ref("")
const commentSubmitting = ref(false)
const commentReplyInput = ref("")
const commentReplyReplyInput = ref("")

const loadArticleDetail = (articleId: number) => {
  getArticleDetail(articleId).then(result => {
    article.value = result
    dataLoaded.value = true
    // 加载作者相关数据
    loadAuthor(result.authorId)
    // 加载评论
    loadArticleComment(articleId)
  })
}

const loadAuthor = (authorId: number) => {
  loadAuthorInfo(authorId)
  loadAuthorRecentArticle(authorId)
}

const loadAuthorInfo = (userId: number) => {
  UserApi.getDetail(userId).then(result => {
    authorInfo.value = result
  })
}
//最近文章
const loadAuthorRecentArticle = (authorId: number) => {
  let req: ArticleRecentReq = {
    authorId: authorId
  }
  queryRecentArticle(req).then(result => {
    recentArticle.value = result
  })
}
//加载评论
const reloadArticleComment = (articleId: number) => {
  articleCommentPage.value = 1
  articleCommentHasMore.value = false
  articleComments.value = []
  loadArticleComment(articleId)
}
const loadArticleComment = (articleId: number) => {
  let req: ArticleCommentPageReq = {
    current: 1,
    size: 10,
    articleId: articleId
  }
  pageArticleComment(req).then(result => {
    articleCommentHasMore.value = result.pages > result.current;
    articleComments.value = result.records
  })
}

const loadMoreArticleComment = (articleId: number) => {
  articleCommentPage.value++
  let req: ArticleCommentPageReq = {
    current: articleCommentPage.value,
    size: 10,
    articleId: articleId
  }
  loadingMoreArticleComment.value = true
  pageArticleComment(req).then(result => {
    articleCommentHasMore.value = result.pages > result.current;
    articleComments.value.push(...result.records)
    loadingMoreArticleComment.value = false
  })
}

//收藏文章
const onStarArticle = (articleId: number, flag: boolean) => {
  let req: ArticleStarReq = {
    articleId: articleId,
    flag: flag
  }
  starArticle(req)
}

const onPublishArticleComment = () => {
  let req: ArticleCommentPublishReq = {
    articleId: article.value.id,
    content: commentInput.value
  }
  commentSubmitting.value = true
  publishArticleComment(req).then(() => {
    ElMessage.success("提交成功")
    article.value.commentCount++;
    //articleComments.value.unshift({content: commentInput.value, createBy: loginStore.nickName, createTime: Jh_timeStampToTime(Jh_getTimeStamp(), '{y}-{m}-{d} {h}:{i}')} as ArticleCommentPageResp)
    commentInput.value = ''
    reloadArticleComment(article.value.id)
  }).finally(() => commentSubmitting.value = false)
}

const handleContentEditorCreated = (editor: IDomEditor) => {
  contentEditorRef.value = editor
  const headers = editor.getElemsByTypePrefix('header')
  contentHeaders = headers.map(header => {
    const text = header.children[0]?.text
    const { id, type } = header
    return {id, type, text}
  })
}

/**
 * 关注/取消关注用户
 * @param userId 被关注人id
 * @param flag true关注 false取消关注
 * @param callback 成功后回调
 * @param onFinally finally回调
 */
const followUser = (userId: number, flag: boolean, callback: Function, onFinally: Function) => {
  let req: UserTypes.UserFollowReq = {
    userId: userId,
    flag: flag
  }
  UserApi.userFollow(req).then(() => {
    callback()
  }).finally(() => {
    onFinally()
  })
}
/**
 * 提交评论回复
 * @param sourceComment 来源评论
 */
const submitCommentReply = (sourceComment: ArticleCommentPageResp) => {
  let req: ArticleCommentReplyPublishReq = {
    sourceCommentId: sourceComment.id,
    parentReplyId: -1,
    repliedUserId: sourceComment.userId,
    content: commentReplyInput.value
  }
  sourceComment.replying = true;
  publishArticleCommentReply(req).then((result)=>{
    sourceComment.replies.push({
      id: result,
      content: `${commentReplyInput.value}`,
      createTime: formatDate(new Date(), '{y}-{m}-{d} {h}:{i}'),
      userId: loginStore.userId,
      userName: loginStore.nickName,
      userAvatar: loginStore.avatar,
      repliedUserName: sourceComment.userName,
    })
    sourceComment.showReplyInput = false
    commentReplyInput.value = ''
  }).finally(()=>sourceComment.replying = false)
}

const submitCommentReplyReply = (sourceCommentReply: ArticleCommentRepliesResp, sourceComment: ArticleCommentPageResp) => {
  let req: ArticleCommentReplyPublishReq = {
    sourceCommentId: sourceComment.id,
    parentReplyId: sourceCommentReply.id,
    repliedUserId: sourceCommentReply.userId,
    content: commentReplyReplyInput.value
  }
  sourceCommentReply.replying = true;
  publishArticleCommentReply(req).then((result)=>{
    sourceComment.replies.push({
      id: result,
      content: `${commentReplyReplyInput.value}`,
      createTime: formatDate(new Date(), '{y}-{m}-{d} {h}:{i}'),
      userId: loginStore.userId,
      userName: loginStore.nickName,
      userAvatar: loginStore.avatar,
      repliedUserName: sourceCommentReply.userName,
    })
    sourceCommentReply.showReplyInput = false
    commentReplyReplyInput.value = ''
  }).finally(()=>sourceCommentReply.replying = false)
}

const scrollToHeader = (anchor: string) => {
  const element = document.getElementById(anchor);
  if (element) {
    element.scrollIntoView({ behavior: 'smooth' });
  }
}

const mountedFunc = () => {
  let articleId = Number(route.params.id)
  if (articleId == null || isNaN(articleId)) {
    ElMessage({
      type: 'error',
      message: '缺少必要参数'
    })
    return
  }
  loadArticleDetail(articleId)
}
//初始加载数据
onMounted(mountedFunc)
// 组件销毁时，也及时销毁编辑器
onBeforeUnmount(() => {
  setTimeout(() => {
    if (contentEditorRef.value != null) contentEditorRef.value.destroy()
  }, 200)
})
</script>

<template>
  <div class="w-full h-full overflow-auto bg-white-soft">
    <div class="mt-6">
      <div class="ui FHContainer">
        <div class="FHMain">
          <div class="FHContent has-aside flex flex-row">
            <div class="content">
              <div v-if="dataLoaded">
                <!--面包屑-->
                <el-breadcrumb separator="/" class="mb-5">
                  <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
                  <el-breadcrumb-item
                      :to="{path: `/article/category/${article.categoryId}`, query: {cn: article.categoryName }}">
                    {{ article.categoryName }}
                  </el-breadcrumb-item>
                </el-breadcrumb>
                <!--文章内容-->
                <div class="bg-white border-box">
                  <h1 class="text-3xl font-bold">{{ article.title }}</h1>
                  <!--作者信息-->
                  <UserPostInfo :user-id="article.authorId" :user-name="article.authorName"
                                :post-time="article.publishedTime"
                                :avatar="article.authorAvatar"
                                class="mt-3"/>
                  <el-divider/>
                  <!-- 目录 -->
                  <div class="ez-toc-container rounded-lg bg-white-soft inline-block py-3 px-2 border" v-show="contentHeaders?.length > 0">
                    <a ><p class="ez-toc-title text-gray-500" @click="showCatalog=!showCatalog"><font-awesome-icon :icon="['far', 'chart-bar']" />索引</p></a>
                    <ul v-show="showCatalog">
                      <li v-for="header in contentHeaders" class="mt-1 ez-toc-li relative pl-3 hover:text-blue-600 text-gray-500">
                        <a :href="`#${header.id}`" @click.prevent="scrollToHeader(header.id)" :class="header.type" class="ez-toc-link py-1 px-2 rounded hover:bg-gray-200 hover:text-blue-600 text-gray-500">{{header.text}}</a>
                      </li>
                    </ul>
                  </div>
                  <div class="mb-6">
                    <Editor
                        style="min-height: 300px"
                        v-model="article.content"
                        :defaultConfig="{readOnly: true}"
                        mode="default"
                        @onCreated="handleContentEditorCreated"/>
                  </div>
                  <!--标签-->
                  <div class="mb-6">
                    <RouterLink :to="`/article/tag/${tag.tagId}?cn=${tag.tagName}`" class="rounded bg-gray-100 pr-2 text-xs inline-block py-1 hover:bg-sky-600 hover:text-white mr-3" v-for="tag in article.tags">
                      <span class="px-2 bg-color-primary rounded text-white py-1">#</span>
                      {{tag.tagName}}
                    </RouterLink>
                  </div>
                  <div>
                    <div class="flex flex-row">
                      <ClickToggleCounter active-icon="/svg/start-selected.svg"
                                          inactive-icon="/svg/start.svg"
                                          :flag="article.hasStar" :count="article.starCount"
                                          @OnInactive="()=>{article.hasStar=false;article.starCount--;onStarArticle(article.id, false)}"
                                          @onActive="()=>{article.hasStar=true;article.starCount++;onStarArticle(article.id, true);}"/>
                      <span class="ml-6"><img alt="Icon" width="18" height="18"
                                              src="/svg/share.svg"
                                              @click=""
                                              class="hover:scale-110"
                                              id="share-btn"/></span>
                    </div>
                  </div>
                </div>
                <!--评论区-->
                <div class="bg-white border-box">
                  <h3 class="widget-title font-bold mb-3">发表回复</h3>
                  <el-input
                      v-model="commentInput"
                      maxlength="200"
                      style="width: 100%;"
                      placeholder="写下您的评论..."
                      show-word-limit
                      type="textarea"
                      :autosize="{minRows:4, maxRows:4}"
                      class="mb-3"
                  />
                  <div class="text-right">
                    <el-button type="primary" @click="onPublishArticleComment" :loading="commentSubmitting"
                               :disabled="isEmptyString(commentInput)">提交
                    </el-button>
                  </div>
                  <div v-if="article.commentCount > 0">
                    <el-divider/>
                    <h3 class="widget-title font-bold mb-3">
                      评论列表({{ formatNumberSimple(article.commentCount) }}条)</h3>
                    <div :id="`comment-${comment.id}`" v-for="comment in articleComments" class="relative">
                      <div class="comment-item-main">
                        <span class="reply-comment-btn absolute right-0 top-0"><el-button type="primary"
                                                                                          :icon="ChatDotSquare" link
                                                                                          @click="comment.showReplyInput = true">回复</el-button></span>
                        <UserPostInfo :user-id="comment.userId" :user-name="comment.userName"
                                      :post-time="comment.createTime"
                                      :avatar="comment.userAvatar"
                                      class="mb-3"/>
                        <p class="ml-10 text-sm">{{ comment.content }}</p>
                      </div>
                      <!--回复输入区-->
                      <div class="ml-10 mt-3 min-h-[30px] rounded" v-if="comment.showReplyInput">
                        <div class="flex flex-row justify-between"><span
                            class="text-sm">回复给 {{ comment.userName }}</span>
                          <el-button :icon="Close" link
                                     @click="commentReplyInput='';comment.showReplyInput = false"></el-button>
                        </div>
                        <el-input
                            v-model="commentReplyInput"
                            maxlength="200"
                            style="width: 100%;"
                            placeholder="写下您的评论..."
                            show-word-limit
                            type="textarea"
                            :autosize="{minRows:4, maxRows:4}"
                            class="my-3"
                        />
                        <div class="text-right">
                          <el-button type="primary" :disabled="isEmptyString(commentReplyInput)"
                                     @click="submitCommentReply(comment)" :loading="comment.replying">提交
                          </el-button>
                        </div>
                      </div>
                      <!--回复列表-->
                      <div v-if="comment?.replies?.length > 0">
                        <div class="bubble-horn"></div>
                        <div class="bubble">
                          <ul class="comment-replies-ul">
                            <li v-for="commentReply in comment.replies"
                                class="w-full py-3 border-b relative comment-replies-li">
                              <div class="reply-comment-item-main">
                                <span class="reply-comment-btn absolute right-0 top-0"><el-button type="primary"
                                                                                                  :icon="ChatDotSquare"
                                                                                                  link
                                                                                                  @click="commentReply.showReplyInput = true">回复</el-button></span>
                                <div class="flex flex-row items-center">
                                  <UserAvatar :size="20" :file-id="commentReply.userAvatar"></UserAvatar>
                                  <span class="ml-2 text-xs">{{ commentReply.userName }}</span>
                                  <span class="ml-2 text-xs">{{ commentReply.createTime }}</span>
                                </div>
                                <div class="ml-7 mt-2 text-sm">
                                  {{ `@${commentReply.repliedUserName}： ${commentReply.content}` }}
                                </div>
                              </div>
                              <!--回复输入区-->
                              <div class="ml-10 mt-3 min-h-[30px] rounded" v-if="commentReply.showReplyInput">
                                <div class="flex flex-row justify-between"><span
                                    class="text-sm">回复给 {{ commentReply.userName }}</span>
                                  <el-button :icon="Close" link
                                             @click="commentReplyReplyInput='';commentReply.showReplyInput = false"></el-button>
                                </div>
                                <el-input
                                    v-model="commentReplyReplyInput"
                                    maxlength="200"
                                    style="width: 100%;"
                                    placeholder="写下您的评论..."
                                    show-word-limit
                                    type="textarea"
                                    :autosize="{minRows:4, maxRows:4}"
                                    class="my-3"
                                />
                                <div class="text-right">
                                  <el-button type="primary" :disabled="isEmptyString(commentReplyReplyInput)" @click="submitCommentReplyReply(commentReply, comment)" :loading="commentReply.replying">提交
                                  </el-button>
                                </div>
                              </div>
                            </li>
                          </ul>
                        </div>
                      </div>
                      <el-divider/>
                    </div>
                    <div class="text-center" v-if="articleCommentHasMore">
                      <el-button type="primary" :loading="loadingMoreArticleComment" plain
                                 @click="loadMoreArticleComment(article.id)">点击查看更多
                      </el-button>
                    </div>
                  </div>

                </div>
              </div>
              <div v-else>
                <el-skeleton/>
              </div>
            </div>
            <div class="aside pt-8">
              <div class="bg-white rounded-lg mb-6 overflow-hidden" v-if="authorInfo != null">
                <div class="profile-cover"
                     :style="{ backgroundImage:  authorInfo.cover ? `url(${FileApis.getDownloadUrl(authorInfo.cover)})`: `url('/images/site/user_profile_backgroup.jpeg')` }"/>
                <div class="avatar-warp mb-4">
                  <RouterLink :to="'/user/center/'+ authorInfo.id">
                    <div class="w-[84px] h-[84px] bg-white flex justify-center items-center" style="border-radius: 50%">
                      <UserAvatar :size="80" :file-id="authorInfo.avatar"></UserAvatar>
                    </div>
                  </RouterLink>
                </div>
                <div class="mb-5">
                  <RouterLink class="guide-a" :to="'/user/center/'+ authorInfo.id">
                    <p class="text-center text-black mb-3 hover-primary">{{ authorInfo.nickname }}</p>
                  </RouterLink>
                  <p class="text-center text-gray-500 mb-3 text-xs">
                    {{ isEmptyString(authorInfo.signature) ? '这个人很懒，什么都没有留下～' : authorInfo.signature }}</p>
                  <div class="grid grid-cols-3 text-center">
                    <div>
                      <span class="text-black text-lg">{{ authorInfo.articleCount }}</span>
                      <p class="text-gray-400 text-sm">文章</p>
                    </div>
                    <div>
                      <span class="text-black text-lg">{{ authorInfo.articleCommentCount }}</span>
                      <p class="text-gray-400 text-sm">评论</p>
                    </div>
                    <div>
                      <span class="text-black text-lg">{{ authorInfo.followedCount }}</span>
                      <p class="text-gray-400 text-sm">粉丝</p>
                    </div>
                  </div>
                </div>
                <div class="text-center mb-5">
                  <el-button type="primary" class="mr-3"
                             @click="following=true;followUser(authorInfo.id, false, ()=>{authorInfo.hasFollow = false;authorInfo.followedCount--}, ()=>following=false)"
                             v-if="authorInfo.hasFollow" plain :loading="following">已关注
                  </el-button>
                  <el-button icon="Plus" type="primary" class="mr-3"
                             @click="following=true;followUser(authorInfo.id, true, ()=>{authorInfo.hasFollow = true;authorInfo.followedCount++}, ()=>following=false)"
                             :loading="following" v-else>关注
                  </el-button>
                  <el-button icon="Message" type="primary" @click="showSysMessageChatDialog = true">私信</el-button>
                </div>
              </div>
              <!--最近文章-->
              <RecentArticleList :articleList="recentArticle" v-if="recentArticle.length > 0"></RecentArticleList>
            </div>
          </div>
        </div>
      </div>
    </div>
    <SysMessageDialog v-if="showSysMessageChatDialog" :to-user-id="authorInfo?.id" @onClose="showSysMessageChatDialog = false"></SysMessageDialog>
  </div>
</template>

<style scoped>

.profile-cover {
  overflow: hidden;
  height: 96px;
  background-size: cover;
}

.avatar-warp {
  margin-top: -40px;
  display: flex;
  justify-content: center;
}

.reply-comment-btn {
  display: none;
}

.comment-item-main:hover .reply-comment-btn {
  display: block;
}

.reply-comment-item-main:hover .reply-comment-btn {
  display: block;
}

/* 气泡样式 */
.bubble-horn {
  margin-left: 40px;
  background-color: #f6f6f6;
  height: 10px;
  clip-path: polygon(
      20px 10px,
      30px 0,
      40px 10px
  )
}

.bubble {
  position: relative; /* 确保内容在裁剪区域内正常显示 */
  padding: 10px 20px;
  margin-left: 40px;
  background-color: #f6f6f6;
  border-radius: 8px; /* 让气泡主体有圆角 */
}

.comment-replies-ul li:last-child {
  border-bottom: 0;
}
.ez-toc-li {
  line-height: 29px;
}
.ez-toc-li:before {
  content: "•";
  position: absolute;
  display: block;
  left: 0;
  top: 0;
  font-size: 1.5em;
  font-weight: bold;
  transition: color 0.3s ease;
}
.ez-toc-li .header2:before {
  content: "\00a0\00a0";
}
.ez-toc-li .header3:before {
  content: "\00a0\00a0\00a0\00a0";
}
.ez-toc-li .header4:before {
  content: "\00a0\00a0\00a0\00a0\00a0\00a0";
}
.ez-toc-li .header5:before {
  content: "\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0";
}
.ez-toc-li .header6:before {
   content: "\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0\00a0";
 }

</style>